#include "../include/head.h"
//copy sb server_dir.c
int split_path(const char *input, char **out_parent, char **out_name) {
    if (!input || !out_parent || !out_name) return -1;

    // 去掉末尾多余的 '/'
    size_t len = strlen(input);
    while (len > 1 && input[len - 1] == '/') {
        len--;
    }

    char *tmp = (char *)malloc(len + 1);
    if (!tmp) return -1;
    memcpy(tmp, input, len);
    tmp[len] = '\0';

    // 找最后一个 '/'
    char *slash = strrchr(tmp, '/');
    if (!slash) {
        // 没有 '/'，父路径为 "."
        *out_parent = strdup(".");
        *out_name   = strdup(tmp);
    } else if (slash == tmp) {
        *out_parent = strdup("/");
        *out_name   = strdup(slash + 1);
    } else {
        *slash = '\0';
        *out_parent = strdup(tmp);
        *out_name   = strdup(slash + 1);
    }

    free(tmp);
    if (!*out_parent || !*out_name) {
        free(*out_parent);
        free(*out_name);
        return -1;
    }
    return 0;
}


int client_puts_comfirm(int target,int args_len,char *args,int netfd,char *now_path_buf)
{
    char argbuf[512]={0};
    memcpy(argbuf,args,args_len);
    char *addr1=strtok(argbuf," ");//客户端文件的地址
    char *addr2=strtok(NULL," ");//服务端要存储的文件的地址
    char *md5=strtok(NULL," ");
    char *filesizebuf=strtok(NULL," ");
    off_t netfilesize = 0;

    struct stat file_stat;
    if (stat(addr1, &file_stat) == -1) {
        printf("server_puts_query stat error\n");
        return -1;
    }
    off_t  filesize = file_stat.st_size;


    sscanf(filesizebuf,"%ld",&netfilesize);

    if(netfilesize == filesize)
    {
        printf("极速快传已完成！\n");
        return 0;
    }
    if(netfilesize != 0)
    {
        printf("指定路径下已有同名文件，是否继续？%ld\n",netfilesize);
        printf("请输入(0:取消 1:续写 2:覆写 ):");
        fflush(stdout);
        int userop;
        scanf("%d",&userop);
        fflush(stdin);
        if(userop == 0)
        {
            return -1;
        }
        else if(userop == 1)
        {
            char sendargs[512]={0};
            sprintf(sendargs,"%s %ld",args,filesize);
            int sendargs_len = strlen(sendargs);
            int sendtype = C_OP_PUTS_BEGIN;
            send(netfd,&sendtype,sizeof(int),MSG_NOSIGNAL);
            send(netfd,&sendargs_len,sizeof(int),MSG_NOSIGNAL);
            send(netfd,sendargs,strlen(sendargs),MSG_NOSIGNAL);
        }
        else if(userop == 2)
        {
            char sendargs[512]={0};
            netfilesize = 0;
            sprintf(sendargs,"%s %s %s %ld %ld",addr1,addr2,md5,netfilesize,filesize);
            int sendargs_len = strlen(sendargs);
            int sendtype = C_OP_PUTS_BEGIN;
            send(netfd,&sendtype,sizeof(int),MSG_NOSIGNAL);
            send(netfd,&sendargs_len,sizeof(int),MSG_NOSIGNAL);
            send(netfd,sendargs,strlen(sendargs),MSG_NOSIGNAL);
        }
    }
    else
    {
        char sendargs[512]={0};
        sprintf(sendargs,"%s %ld",args,filesize);
        printf("sendargs = %s\n", sendargs);
        int sendargs_len = strlen(sendargs);
        int sendtype = C_OP_PUTS_BEGIN;
        send(netfd,&sendtype,sizeof(int),MSG_NOSIGNAL);
        send(netfd,&sendargs_len,sizeof(int),MSG_NOSIGNAL);
        send(netfd,sendargs,strlen(sendargs),MSG_NOSIGNAL);
    }

    int open_fd = open(addr1,O_RDWR);
    lseek(open_fd,netfilesize,SEEK_SET);

    long processed = netfilesize;
    long max_size = (long)2*1024*1024*1024;
    //long max_size = (long)512*1024*1024;//512M
    while(processed<filesize)
    {
        long sendsize = filesize - processed > (max_size)?max_size:filesize - processed;
        char* p = (char*)mmap(NULL,sendsize,PROT_READ|PROT_WRITE,MAP_SHARED,open_fd,processed);
        send(netfd,(void*)p,sendsize,MSG_NOSIGNAL);
        munmap(p,sendsize);
        processed+=sendsize;
        printf("%ld/%ld\n",processed,filesize);
    }
    close(open_fd);
    printf("client send end %ld\n",processed);
    return 0;
}
int client_gets_comfirm(int target,int args_len,char *args,int netfd,char *now_path_buf)
{
    char argbuf[512]={0};
    memcpy(argbuf,args,args_len);
    char *addr1=strtok(argbuf," ");//客户端文件的地址
    char *addr2=strtok(NULL," ");//服务端要存储的文件的地址
    char *netfilesizebuf=strtok(NULL," ");
    char* md5 = strtok(NULL," ");
    off_t netfilesize = 0;
    sscanf(netfilesizebuf,"%ld",&netfilesize);

    char *filename;
    char *fileFatherPath;
    split_path(addr1,&fileFatherPath,&filename);

    char localFilePath[512] = {0}; 
    if(addr2[strlen(addr2)-1]=='/')
    {
        sprintf(localFilePath,"%s%s",addr2,filename);
    }
    else
    {
        sprintf(localFilePath,"%s/%s",addr2,filename);
    }
    printf("%s %s %s %s\n", addr1, addr2, filename, localFilePath);
    // pause();
    int open_fd = 0;

    off_t filesize = 0;
    if(access(localFilePath,F_OK)!=-1)
    {
        struct stat file_stat;
        if (stat(localFilePath, &file_stat) == -1) {
            //printf("server_gets_query open filePath = %s\n", filePath);
            //printf("server_puts_query 5 stat error\n");
            free(filename);
            free(fileFatherPath);
            return -1;
        }

        filesize = file_stat.st_size;
        printf("本地路径下存在同名文件: %s,是否继续?\n",localFilePath);
        if(filesize < netfilesize)
        {
            printf("请输入(0:取消 1:续写 2:覆写):");
            fflush(stdout);
            int userop;
            scanf("%d",&userop);
            // fflush(stdin);
            int c;
            while((c=getchar())!='\n' && c!=EOF){
            };
            if (userop == 0)
            {
                printf("用户取消下载\n");
                free(filename);
                free(fileFatherPath);
                return -1;
            }
            else if(userop==1)
            {
                int type = C_OP_GETS_BEGIN;
                char sendargs[1024]={0};
                filesize = filesize - (filesize % 4096);
                sprintf(sendargs,"%s %s %ld %s",addr1,addr2,filesize,md5);
                int sendargs_len = strlen(sendargs);
                send(netfd,&type,sizeof(int),MSG_NOSIGNAL);
                send(netfd,&sendargs_len,sizeof(int),MSG_NOSIGNAL);
                send(netfd,sendargs,sendargs_len,MSG_NOSIGNAL);
                open_fd = open(localFilePath,O_RDWR);
                lseek(open_fd,filesize,SEEK_SET);
            }
            else
            {
                int type = C_OP_GETS_BEGIN;
                char sendargs[1024]={0};
                filesize = 0;
                sprintf(sendargs,"%s %s %ld %s",addr1,addr2,filesize,md5);
                int sendargs_len = strlen(sendargs);
                send(netfd,&type,sizeof(int),MSG_NOSIGNAL);
                send(netfd,&sendargs_len,sizeof(int),MSG_NOSIGNAL);
                send(netfd,sendargs,sendargs_len,MSG_NOSIGNAL);
                open_fd = open(localFilePath,O_RDWR|O_TRUNC);
                lseek(open_fd,0,SEEK_SET);
            }
        }
        else
        {

            printf("请输入(0:取消 1:覆写):");
            fflush(stdout);
            int userop;
            scanf("%d",&userop);
            int c;
            while ((c = getchar()) != '\n' && c != EOF)
            {
            };
            if(userop == 0)
            {
                printf("用户取消下载\n");
                free(filename);
                free(fileFatherPath);
                return -1;
            }
            else
            {
                int type = C_OP_GETS_BEGIN;
                char sendargs[1024]={0};
                filesize = 0;
                sprintf(sendargs,"%s %s %ld %s",addr1,addr2,filesize,md5);
                int sendargs_len = strlen(sendargs);
                send(netfd,&type,sizeof(int),MSG_NOSIGNAL);
                send(netfd,&sendargs_len,sizeof(int),MSG_NOSIGNAL);
                send(netfd,sendargs,sendargs_len,MSG_NOSIGNAL);
                open_fd = open(localFilePath,O_RDWR);
                lseek(open_fd,0,SEEK_SET);
            }
        }
    }
    else
    {
        open_fd = open(localFilePath,O_CREAT|O_RDWR,0666);
        int type = C_OP_GETS_BEGIN;
        char sendargs[1024]={0};
        filesize = 0;
        sprintf(sendargs,"%s %s %ld %s",addr1,addr2,filesize,md5);
        int sendargs_len = strlen(sendargs);
        send(netfd,&type,sizeof(int),MSG_NOSIGNAL);
        send(netfd,&sendargs_len,sizeof(int),MSG_NOSIGNAL);
        send(netfd,sendargs,sendargs_len,MSG_NOSIGNAL);
        lseek(open_fd,0,SEEK_SET);
    }
    
    long processed = filesize;
    //long max_size = (long)512*1024*1024;
    char recvbuf[4096]={0};
    while(processed<netfilesize)
    {
        bzero(recvbuf,4096);
        int recvsize = recv(netfd,recvbuf,4096,0);
        if(recvsize ==0)
        {
            break;
        }
        write(open_fd,recvbuf,recvsize);
        processed+=recvsize;
    }
    close(open_fd);
    free(filename);
    free(fileFatherPath);
    printf("gets end\n");
    return 0;
}
